{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### VGGNet\n",
    "    VGGNet诞生于2014年，当年ImageNet竞赛的亚军，Top5错误率减小到7.3%\n",
    "    K.Simonyan, A.Zisserman. Very Deep Convolutional Networks for Large-Scale Image Recognition.In ICLR,2015.\n",
    "    \n",
    "    结构：十三层卷积，三层全连接\n",
    "    输入：32*32*3\n",
    "    C（核：64*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    \n",
    "    C（核：64*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    P（max，核：2*2，步长：2）\n",
    "    D（0.2）\n",
    "    \n",
    "    C（核：128*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "\n",
    "    C（核：128*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    P（max，核：2*2，步长：2）\n",
    "    D（0.2）\n",
    "    \n",
    "    C（核：256*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "\n",
    "    C（核：256*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    \n",
    "    C（核：256*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    P（max，核：2*2，步长：2）\n",
    "    D（0.2\n",
    "\n",
    "    C（核：512*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "\n",
    "    C（核：512*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "\n",
    "    C（核：512*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    P（max，核：2*2，步长：2）\n",
    "    D（0.2）\n",
    "\n",
    "    C（核：512*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    \n",
    "    C（核：512*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    \n",
    "    C（核：512*3*3，步长：1，填充：same ）\n",
    "    B（Yes）\n",
    "    A（relu）\n",
    "    P（max，核：2*2，步长：2）\n",
    "    D（0.2）\n",
    "    \n",
    "    Dense（神经元：512，激活：relu，Dropout：0.2）\n",
    "    Dense（神经元：512，激活：relu，Dropout：0.2）\n",
    "    Dense（神经元：10，激活：softmax）\n",
    "    \n",
    "    在设计这个网络是，卷积核的个数从64→128→256→512\n",
    "    因为越靠后特征图尺寸越小，通过增加卷积核的个数，增加了特征图的深度保持了信息的承载能力。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import os\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense\n",
    "from tensorflow.keras import Model\n",
    "\n",
    "np.set_printoptions(threshold=np.inf)\n",
    "\n",
    "cifar10 = tf.keras.datasets.cifar10\n",
    "(x_train, y_train), (x_test, y_test) = cifar10.load_data()\n",
    "x_train, x_test = x_train / 255.0, x_test / 255.0\n",
    "\n",
    "\n",
    "class VGG16(Model):\n",
    "    def __init__(self):\n",
    "        super(VGG16, self).__init__()\n",
    "        self.c1 = Conv2D(filters=64, kernel_size=(3, 3), padding='same')  # 卷积层1\n",
    "        self.b1 = BatchNormalization()  # BN层1\n",
    "        self.a1 = Activation('relu')  # 激活层1\n",
    "        self.c2 = Conv2D(filters=64, kernel_size=(3, 3), padding='same', )\n",
    "        self.b2 = BatchNormalization()  # BN层1\n",
    "        self.a2 = Activation('relu')  # 激活层1\n",
    "        self.p1 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')\n",
    "        self.d1 = Dropout(0.2)  # dropout层\n",
    "\n",
    "        self.c3 = Conv2D(filters=128, kernel_size=(3, 3), padding='same')\n",
    "        self.b3 = BatchNormalization()  # BN层1\n",
    "        self.a3 = Activation('relu')  # 激活层1\n",
    "        self.c4 = Conv2D(filters=128, kernel_size=(3, 3), padding='same')\n",
    "        self.b4 = BatchNormalization()  # BN层1\n",
    "        self.a4 = Activation('relu')  # 激活层1\n",
    "        self.p2 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')\n",
    "        self.d2 = Dropout(0.2)  # dropout层\n",
    "\n",
    "        self.c5 = Conv2D(filters=256, kernel_size=(3, 3), padding='same')\n",
    "        self.b5 = BatchNormalization()  # BN层1\n",
    "        self.a5 = Activation('relu')  # 激活层1\n",
    "        self.c6 = Conv2D(filters=256, kernel_size=(3, 3), padding='same')\n",
    "        self.b6 = BatchNormalization()  # BN层1\n",
    "        self.a6 = Activation('relu')  # 激活层1\n",
    "        self.c7 = Conv2D(filters=256, kernel_size=(3, 3), padding='same')\n",
    "        self.b7 = BatchNormalization()\n",
    "        self.a7 = Activation('relu')\n",
    "        self.p3 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')\n",
    "        self.d3 = Dropout(0.2)\n",
    "\n",
    "        self.c8 = Conv2D(filters=512, kernel_size=(3, 3), padding='same')\n",
    "        self.b8 = BatchNormalization()  # BN层1\n",
    "        self.a8 = Activation('relu')  # 激活层1\n",
    "        self.c9 = Conv2D(filters=512, kernel_size=(3, 3), padding='same')\n",
    "        self.b9 = BatchNormalization()  # BN层1\n",
    "        self.a9 = Activation('relu')  # 激活层1\n",
    "        self.c10 = Conv2D(filters=512, kernel_size=(3, 3), padding='same')\n",
    "        self.b10 = BatchNormalization()\n",
    "        self.a10 = Activation('relu')\n",
    "        self.p4 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')\n",
    "        self.d4 = Dropout(0.2)\n",
    "\n",
    "        self.c11 = Conv2D(filters=512, kernel_size=(3, 3), padding='same')\n",
    "        self.b11 = BatchNormalization()  # BN层1\n",
    "        self.a11 = Activation('relu')  # 激活层1\n",
    "        self.c12 = Conv2D(filters=512, kernel_size=(3, 3), padding='same')\n",
    "        self.b12 = BatchNormalization()  # BN层1\n",
    "        self.a12 = Activation('relu')  # 激活层1\n",
    "        self.c13 = Conv2D(filters=512, kernel_size=(3, 3), padding='same')\n",
    "        self.b13 = BatchNormalization()\n",
    "        self.a13 = Activation('relu')\n",
    "        self.p5 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')\n",
    "        self.d5 = Dropout(0.2)\n",
    "\n",
    "        self.flatten = Flatten()\n",
    "        self.f1 = Dense(512, activation='relu')\n",
    "        self.d6 = Dropout(0.2)\n",
    "        self.f2 = Dense(512, activation='relu')\n",
    "        self.d7 = Dropout(0.2)\n",
    "        self.f3 = Dense(10, activation='softmax')\n",
    "\n",
    "    def call(self, x):\n",
    "        x = self.c1(x)\n",
    "        x = self.b1(x)\n",
    "        x = self.a1(x)\n",
    "        x = self.c2(x)\n",
    "        x = self.b2(x)\n",
    "        x = self.a2(x)\n",
    "        x = self.p1(x)\n",
    "        x = self.d1(x)\n",
    "\n",
    "        x = self.c3(x)\n",
    "        x = self.b3(x)\n",
    "        x = self.a3(x)\n",
    "        x = self.c4(x)\n",
    "        x = self.b4(x)\n",
    "        x = self.a4(x)\n",
    "        x = self.p2(x)\n",
    "        x = self.d2(x)\n",
    "\n",
    "        x = self.c5(x)\n",
    "        x = self.b5(x)\n",
    "        x = self.a5(x)\n",
    "        x = self.c6(x)\n",
    "        x = self.b6(x)\n",
    "        x = self.a6(x)\n",
    "        x = self.c7(x)\n",
    "        x = self.b7(x)\n",
    "        x = self.a7(x)\n",
    "        x = self.p3(x)\n",
    "        x = self.d3(x)\n",
    "\n",
    "        x = self.c8(x)\n",
    "        x = self.b8(x)\n",
    "        x = self.a8(x)\n",
    "        x = self.c9(x)\n",
    "        x = self.b9(x)\n",
    "        x = self.a9(x)\n",
    "        x = self.c10(x)\n",
    "        x = self.b10(x)\n",
    "        x = self.a10(x)\n",
    "        x = self.p4(x)\n",
    "        x = self.d4(x)\n",
    "\n",
    "        x = self.c11(x)\n",
    "        x = self.b11(x)\n",
    "        x = self.a11(x)\n",
    "        x = self.c12(x)\n",
    "        x = self.b12(x)\n",
    "        x = self.a12(x)\n",
    "        x = self.c13(x)\n",
    "        x = self.b13(x)\n",
    "        x = self.a13(x)\n",
    "        x = self.p5(x)\n",
    "        x = self.d5(x)\n",
    "\n",
    "        x = self.flatten(x)\n",
    "        x = self.f1(x)\n",
    "        x = self.d6(x)\n",
    "        x = self.f2(x)\n",
    "        x = self.d7(x)\n",
    "        y = self.f3(x)\n",
    "        return y\n",
    "\n",
    "\n",
    "model = VGG16()\n",
    "\n",
    "model.compile(optimizer='adam',\n",
    "              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),\n",
    "              metrics=['sparse_categorical_accuracy'])\n",
    "\n",
    "checkpoint_save_path = \"./checkpoint/VGG16.ckpt\"\n",
    "if os.path.exists(checkpoint_save_path + '.index'):\n",
    "    print('-------------load the model-----------------')\n",
    "    model.load_weights(checkpoint_save_path)\n",
    "\n",
    "cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,\n",
    "                                                 save_weights_only=True,\n",
    "                                                 save_best_only=True)\n",
    "\n",
    "history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,\n",
    "                    callbacks=[cp_callback])\n",
    "model.summary()\n",
    "\n",
    "# print(model.trainable_variables)\n",
    "file = open('./weights.txt', 'w')\n",
    "for v in model.trainable_variables:\n",
    "    file.write(str(v.name) + '\\n')\n",
    "    file.write(str(v.shape) + '\\n')\n",
    "    file.write(str(v.numpy()) + '\\n')\n",
    "file.close()\n",
    "\n",
    "###############################################    show   ###############################################\n",
    "\n",
    "# 显示训练集和验证集的acc和loss曲线\n",
    "acc = history.history['sparse_categorical_accuracy']\n",
    "val_acc = history.history['val_sparse_categorical_accuracy']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "plt.subplot(1, 2, 1)\n",
    "plt.plot(acc, label='Training Accuracy')\n",
    "plt.plot(val_acc, label='Validation Accuracy')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(loss, label='Training Loss')\n",
    "plt.plot(val_loss, label='Validation Loss')\n",
    "plt.title('Training and Validation Loss')\n",
    "plt.legend()\n",
    "plt.show()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
